/**
 *  tp1
 *  Author: minhvv
 *  Description: Une foret brule
Les pompier vont pour eteindre le feu
 */
 
model tp1
 
global {
        int env_size <- 100 ;
        int num_of_cycle_to_refresh_gui <- 4;   //sau bao nhieu cycle ve lai gui
        int num_of_cycle_to_refresh_chart <- 9; //sau bao nhieu cycle ve lai chart
       
        // feu
        int num_of_feux <- 6;
        float proba_propagation <- 0.1;         // tuong ung 10%: ti le lan toa khi cay bi chay
        float distance_propagation <- 1.2;      // khoang cach dam chay co the lan toa
       
        // tree
        int num_of_trees <- 1000 ;
        int max_tree_dead_time <- 500;          // MAX thoi gian chay cua mot cay
        int min_tree_dead_time <- 200;          // MIN thoi gian chay cua mot cay
        int propagation_time <- 100;            // khi chay, sau khoang thoi gian nay no se lan sang cay khac
        int restore_time_when_watering <- 10;   // thoi gian linh cuu hoa can dung lai o mot cay de tuoi nuoc
        int reborn_time <- 20;                  // tgian hoi sinh cay (tu trang thai protected -> trang thai khoi dau
 
        // pompier
        int num_of_pompiers <- 10;
        float pompier_speed <- 1.2;             // toc do di chuyen binh thuong
        float pompier_spped_increase <- 1.5;    // khi can di chuyen den mot cay bi chay de tuoi nuoc
                                                // toc do linh cuu hoa se duoc nhan voi so nay
        float pompier_vision <- 2.0;            // tam nhin cua linh cuu hoa ( de thay duoc cac cay bi chay quanh no
       
        init {
                create tree
                        number : int ( num_of_trees ) {}
                       
                create pompier
                        number : int ( num_of_pompiers ) {}
                       
                ask num_of_feux
                        among list (tree) {
                                set state <- 'burning';
                                set dead_time <- rnd(max_tree_dead_time) + min_tree_dead_time;
                                                // khoi tao thoi gian chay
                                                // moi cay co thoi gian chay khac nhau
                                                // de chung khong chet cung luc
                        }
        }
}
 
environment
        height: env_size
        width : env_size
        torus : false
;
 
species name: tree
        skills : [ situated , visible ]
        control: fsm
{
        rgb color <- rgb('white');
        float size <- rnd(1) + 1.0 ;
        geometry shape <- circle ( size );
       
        int dead_time <- 0;                     // thoi gian chay cua moi cay
                                                // duoc random khi cai cay bat dau chay
        bool reborn <- false;                   // co danh dau ( cay duoc cuu nho linh cuu hoa
       
        const location
                type: point
                init: point ( [
                        rnd ( env_size - 2 * size ) + size ,
                        rnd ( env_size - 2 * size ) + size
                ] ) ;
       
        aspect defautl {
                draw
                        geometry:       shape
                        color:          color
                ;
        }
       
        state intact initial : true {
                enter {
                        set color <- rgb ([ 0 , rnd ( 155 ) + 100 , 0 ]) ;
                        if (dead_time > 0) {
                                set reborn <- true;
                        }
                }
        }
       
        state protected {
                enter {
                        let protected_duration <- 0;    // thoi gian "duoc bao ve" duoc tuoi nuoc khi cay bi chay
                        set color <- rgb([0, 0, rnd(155) + 100]);
                }
               
                set protected_duration <- protected_duration + 1;
               
                transition
                        to:     'intact'
                        when:   protected_duration > reborn_time
                                                // khi thoi gian tuoi nuoc > thoi gian can de phuc hoi
                                                // cay tro ve trang thai ban dau
                                                // va co reborn cua cay duoc bat
                ;
        }
       
        state burning {
                enter {
                        let duration <- 0;      // khoi tao thoi gian cay bi chay
                }
                set duration <- duration + 1;
 
                // khi chay se thay doi dan mau sac tu xanh sang do
                // thanh phan "r" trong rgb tang dan ( tu 0 -> 255)
                // thanh phan "g" trong rgb giam dan ( tu 255 -> 0)
                let deltaColor <- int(255 * duration / dead_time);
                set color <- rgb([
                        (color.red + deltaColor > 255) ? 255 : (color.red + deltaColor),
                        (color.green - deltaColor < 0) ? 0 : (color.green - deltaColor),
                        0
                ]);
               
                // khi cay bi chay, no khong lan luon sang cay ben canh
                // no phai chay trong khoang thoi gian (propagation_time)
                // thi moi lan sang cay khac
                if (duration > propagation_time) {
                        ask (
                                self neighbours_at(distance_propagation) // tat ca hang xom trong pham vi nao do
                                of_species (species(self))               // cung loai voi no
                                where(each.state = 'intact')             // ma chua bi chay
                        ){
                                if flip(proba_propagation) {             // theo ti le
                                        set state <- 'burning';          // se bi chay
                                        set dead_time <- rnd(max_tree_dead_time) + min_tree_dead_time;
                                }
                        }
                }
               
                transition
                        to:     'destroyed'
                        when:   duration > dead_time
                ;              
        }
       
        state destroyed final : true {
                set color <- rgb([30, 30, 30]);
        }
       
}
 
species name: pompier skills : [visible, moving ] {
        const color
                type: rgb
                init: rgb ( 'yellow' );
        const size
                type: float
                init: 3.0 ;
        geometry shape <- square ( size );
        const location
                type: point
                init: point([
                        rnd(env_size - 2 * size) + size,
                        rnd(env_size - 2 * size) + size
                ]);
        float speed <- pompier_speed ;
       
        tree goal <- nil;               // target cua pompier, trong mot thoi diem no chi cuu duoc 1 cay
        int watering_time <- 0;         // thoi gian dung lai tuoi nuoc o mot cai cay bi chay
       
        aspect default {
                draw
                        geometry:       shape
                        color:          color
                ;
        }
       
        // NOTE: reflex luon duoc thuc hien trong moi cycle
        // action chi thuc hien khi duoc goi
 
        reflex updating
                when: (goal != nil)             // khi pompier co target (goal)
        {                                       // no luon check xem cay do co dang bi chay khong
                        set goal <- (goal.state = 'burning') ? (goal) : (nil) ;
        }
       
        reflex patrolling
                when: (goal = nil)              // khi no khong co target, no se chay loanh quanh
        {                                       // note: khi no co target, no se dung lai tuoi nuoc
                do
                        action: wander          // built-in action, di lung tung
                        amplitude : 180         // quyet dinh huong di chuyen, dung de random heading
                                                // (heading: do lon goc mo dinh huong di chuyen cho agent)
                ;
               
                let burning_neighbours                                  // list nhung thang hang xom
                        type: list
                        value: self neighbours_at pompier_vision        // nam trong tam nhin cua pompier
                                of_species (tree)                       // ma la cay
                                where (each.state = 'burning')          // dang bi chay
                ;
               
                if (not empty(burning_neighbours)) {                    // neu list nay khong rong
                        set goal <- first (                             // thi chon phan tu dau tien la target
                                burning_neighbours sort_by (self distance_to each) //uu tien em gan nhat
                        );
                }
        }
       
        reflex targeting                                                // khi da co muc tieu
                when: (goal != nil)    
        {
                do goto
                        target: goal
                        speed:  speed * pompier_spped_increase          // thi chay den voi toc do nhanh hon
                ;
        }
       
        reflex watering                                                 // va dung lai o cay bi chay
                when: (goal != nil)                                     // de tuoi nuoc
        {
                set watering_time <- watering_time + 1;                
                if (watering_time > restore_time_when_watering) {       // can tuoi du thoi gian
                        do protect_tree;
                }
        }
 
        action protect_tree {
                set goal.state <- 'protected';
                set goal <- nil;
                set watering_time <- 0;
        }
}
 
experiment tp1 type : gui {
        output {
                display Forest refresh_every : num_of_cycle_to_refresh_gui {
                        species tree
                                aspect: default
                        ;
                       
                        species pompier
                                aspect: default;
                }
 
//                ve mot cai do thi de dem so cay bi chay, cay duoc cuu
                display TreeState refresh_every: num_of_cycle_to_refresh_chart {
                        chart state_of_trees
                                type:   'series' {
                                        data burning
                                                value: list(tree) count(each.state = 'burning')
                                                color: rgb('red')
                                                style: step;
                                        data destroyed
                                                value: list(tree) count(each.state = 'destroyed')
                                                color: rgb('black')
                                                style: step;
                                        data protected
                                                value: list(tree) count(each.state = 'protected')
                                                color: rgb('blue')
                                                style: step;
                                        data reborn
                                                value: list(tree) count(each.state = 'intact' and each.reborn = true)
                                                color: rgb('green')
                                                style: line;
                                }
                }
//              display tree_distribution {
//                      chart td_diagram type : pie {
//                              data under_4m value : length ( list ( tree ) where ( each . size < 4 ) ) ;
//                              data above_7m value : length ( list ( tree ) where ( each . size > 7 ) ) ;
//                              data between_4m_and_7m value : length ( list ( tree ) where ( ( each . size
//                              >= 4 ) and ( each . size <= 7 ) ) ) ;
//                      }
//              }
//              monitor tree_counter value : length ( list ( tree ) where ( each . size > 4 )
//              ) ;
 
//              inspect name: 'Agent' type : agent ;
//              inspect name: 'Species' type : species ;
        }
}